module klang.ir.内联汇编.InlineAsm;
import 全局;
import klang.编译.核心.核心_: 整数_, 按字符分割, 查找索引;
import 编译数字 = 编译数字.编译;
import klang.编译.类型.枚举值.枚举值_: 字符_;
import klang.ir.类型.IR类型_: 函数类型_, TypeID_, 结构类型_;
enum ConstraintPrefix : int {
    isInput = 0,
    isOutput = 1,
    isClobber = 2 // '~x'
}
enum Helpers : uint {
    // Fixed operands on an INLINEASM SDNode.
    Op_InputChain = 0u,
    Op_AsmString = 1u,
    Op_MDNode = 2u,
    Op_ExtraInfo = 3u,
    Op_FirstOperand = 4u,
    // Fixed operands on an INLINEASM MachineInstr.
    MIOp_AsmString = 0u,
    MIOp_ExtraInfo = 1u,
    MIOp_FirstOperand = 2u,
    // Interpretation of the MIOp_ExtraInfo bit field.
    Extra_HasSideEffects = 1u,
    Extra_IsAlignStack = 2u,
    Extra_AsmDialect = 4u,
    Extra_MayLoad = 8u,
    Extra_MayStore = 16u,
    Extra_IsConvergent = 32u,
    // Inline asm operands map to multiple SDNode / MachineInstr operands.
    // The first operand is an immediate describing the asm operand, the low
    // bits is the kind:
    Kind_RegUse = 1u,
    Kind_RegDef = 2u,
    Kind_RegDefEarlyClobber = 3u,
    Kind_Clobber = 4u,
    Kind_Imm = 5u,
    Kind_Mem = 6u,
    // Memory constraint codes.
    // These could be tablegenerated but there's little need to do that since
    // there's plenty of space in the encoding to support the union of all
    // constraint codes 循环 all targets.
    Constraint_Unknown = 0u,
    Constraint_es = 1u,
    Constraint_i = 2u,
    Constraint_m = 3u,
    Constraint_o = 4u,
    Constraint_v = 5u,
    Constraint_A = 6u,
    Constraint_Q = 7u,
    Constraint_R = 8u,
    Constraint_S = 9u,
    Constraint_T = 10u,
    Constraint_Um = 11u,
    Constraint_Un = 12u,
    Constraint_Uq = 13u,
    Constraint_Us = 14u,
    Constraint_Ut = 15u,
    Constraint_Uv = 16u,
    Constraint_Uy = 17u,
    Constraint_X = 18u,
    Constraint_Z = 19u,
    Constraint_ZC = 20u,
    Constraint_Zy = 21u,
    Constraints_Max = 21u,
    Constraints_ShiftAmount = 16u,
    Flag_MatchingOperand = 2147483648u
}
enum AsmDialect : int {
    AD_ATT = 0,
    AD_Intel = 1
}
struct ConstraintInfo {
    ConstraintPrefix Type; //= ConstraintPrefix.isInput;
    bool isEarlyClobber; // = 假;e "0", this will be 4).
    long MatchingInput; // = -1;
    bool isCommutative; // = 假;.
    bool isIndirect; //= 假;
    dstring[] Codes;
    bool isMultipleAlternative; // = 假;
    SubConstraintInfo[] multipleAlternatives;
    long currentAlternativeIndex; // = 0;
}
struct SubConstraintInfo {
    long MatchingInput; // = -1;
    dstring[] Codes;
}
dstring getMemConstraintName(Helpers Constraint) {
    switch (Constraint) {
        case Helpers.Constraint_es: {
            return "es"d;
        }
        case Helpers.Constraint_i: {
            return "i"d;
        }
        case Helpers.Constraint_m: {
            return "m"d;
        }
        case Helpers.Constraint_o: {
            return "o"d;
        }
        case Helpers.Constraint_v: {
            return "v"d;
        }
        case Helpers.Constraint_Q: {
            return "Q"d;
        }
        case Helpers.Constraint_R: {
            return "R"d;
        }
        case Helpers.Constraint_S: {
            return "S"d;
        }
        case Helpers.Constraint_T: {
            return "T"d;
        }
        case Helpers.Constraint_Um: {
            return "Um"d;
        }
        case Helpers.Constraint_Un: {
            return "Un"d;
        }
        case Helpers.Constraint_Uq: {
            return "Uq"d;
        }
        case Helpers.Constraint_Us: {
            return "Us"d;
        }
        case Helpers.Constraint_Ut: {
            return "Ut"d;
        }
        case Helpers.Constraint_Uv: {
            return "Uv"d;
        }
        case Helpers.Constraint_Uy: {
            return "Uy"d;
        }
        case Helpers.Constraint_X: {
            return "X"d;
        }
        case Helpers.Constraint_Z: {
            return "Z"d;
        }
        case Helpers.Constraint_ZC: {
            return "ZC"d;
        }
        case Helpers.Constraint_Zy: {
            return "Zy"d;
        }
        default: {
            assert(false, "xxx"c);
            return ""d;
        }
    }
}
dstring getKindName(Helpers Kind) {
    switch (Kind) {
        case Helpers.Kind_RegUse: {
            return "reguse"d;
        }
        case Helpers.Kind_RegDef: {
            return "regdef"d;
        }
        case Helpers.Kind_RegDefEarlyClobber: {
            return "regdef-ec"d;
        }
        case Helpers.Kind_Clobber: {
            return "clobber"d;
        }
        case Helpers.Kind_Imm: {
            return "imm"d;
        }
        case Helpers.Kind_Mem: {
            return "mem"d;
        }
        default: {
            assert(false, "xxx"c);
            return ""d;
        }
    }
}
dstring[] getExtraInfoNames(Helpers ExtraInfo) {
    dstring[] Result = [];
    if ((ExtraInfo & Helpers.Extra_HasSideEffects) != 0) {
        .追加!(dstring)(Result, "sideeffect"d);
    }
    if ((ExtraInfo & Helpers.Extra_MayLoad) != 0) {
        .追加!(dstring)(Result, "mayload"d);
    }
    if ((ExtraInfo & Helpers.Extra_MayStore) != 0) {
        .追加!(dstring)(Result, "maystore"d);
    }
    if ((ExtraInfo & Helpers.Extra_IsConvergent) != 0) {
        .追加!(dstring)(Result, "isconvergent"d);
    }
    if ((ExtraInfo & Helpers.Extra_IsAlignStack) != 0) {
        .追加!(dstring)(Result, "alignstack"d);
    }
    AsmDialect Dialect = (ExtraInfo & Helpers.Extra_AsmDialect) == 0 ? AsmDialect.AD_ATT : AsmDialect.AD_Intel;
    if (Dialect == AsmDialect.AD_ATT) {
        .追加!(dstring)(Result, "attdialect"d);
    }
    if (Dialect == AsmDialect.AD_Intel) {
        .追加!(dstring)(Result, "inteldialect"d);
    }
    return Result;
}
bool hasMatchingInput(ConstraintInfo info) {
    return info.MatchingInput != -1;
}
SubConstraintInfo[] resize(SubConstraintInfo[] multipleAlternatives, long newL) {
    size_t oldL = multipleAlternatives.length;
    if (oldL == newL) {
        return multipleAlternatives;
    }
    if (oldL > newL) {
        {
            for (long i = newL; i < oldL; ++i) {
            }
        }
        return multipleAlternatives;
    }
    {
        for (size_t i = oldL; i < newL; ++i) {
            SubConstraintInfo ···tempS·0·_1;
            {
                ···tempS·0·_1.MatchingInput = -1;
                ···tempS·0·_1.Codes = [];
            }
            .追加!(SubConstraintInfo)(cast(SubConstraintInfo[])(multipleAlternatives), ···tempS·0·_1);
        }
    }
    return multipleAlternatives;
}
bool AsmParse(ConstraintInfo that, dstring Str, ConstraintInfo[] ConstraintsSoFar) {
    long I = 0;
    long E = Str.length;
    size_t multipleAlternativeCount = 按字符分割(Str, 字符_.或号).length;
    int multipleAlternativeIndex = 0;
    dstring[] pCodes = that.Codes;
    that.isMultipleAlternative = multipleAlternativeCount > 1;
    if (that.isMultipleAlternative) {
        that.multipleAlternatives = .resize(that.multipleAlternatives, multipleAlternativeCount);
        pCodes = that.multipleAlternatives[0].Codes;
    }
    that.Type = ConstraintPrefix.isInput;
    that.isEarlyClobber = false;
    that.MatchingInput = -1;
    that.isCommutative = false;
    that.isIndirect = false;
    that.currentAlternativeIndex = 0;
    dchar ch = (cast()(Str[I]));
    if (ch == 字符_.波折) {
        that.Type = ConstraintPrefix.isClobber;
        ++I;
        ch = (cast()(Str[I]));
        if (I != E && ch != 字符_.左大括号) {
            return true;
        }
    }
    else if (ch == 字符_.等号) {
        ++I;
        ch = (cast()(Str[I]));
        that.Type = ConstraintPrefix.isOutput;
    }
    if (I == E) {
        return true;
    }
    bool DoneWithModifiers = false;
    ch = (cast()(Str[I]));
    while(!DoneWithModifiers) {
        switch (ch) {
            case 字符_.且号: {
                if (that.Type != ConstraintPrefix.isOutput || that.isEarlyClobber) {
                    return true;
                }
                that.isEarlyClobber = true;
                break;
            }
            case 字符_.百分: {
                if (that.Type == ConstraintPrefix.isClobber || that.isCommutative) {
                    return true;
                }
                that.isCommutative = true;
                break;
            }
            case 字符_.井号:
            case 字符_.星号: {
                return true;
            }
            default: {
                DoneWithModifiers = true;
                break;
            }
        }
        if (!DoneWithModifiers) {
            ++I;
            ch = (cast()(Str[I]));
            if (I == E) {
                return true;
            }
        }
    }
    while(I != E) {
        if (ch == 字符_.左大括号) {
            long ConstraintEnd = 查找索引(Str, "}"d, I + 1);
            if (ConstraintEnd == E) {
                return true;
            }
            .追加!(dstring)(pCodes, Str[I .. ConstraintEnd + 1 - I]);
            I = ConstraintEnd + 1;
            ch = (cast()(Str[I]));
        }
        else if (ch >= 字符_.数_0 && ch <= 字符_.数_9) {
            long NumStart = I;
            while(I != E && ch >= 字符_.数_0 && ch <= 字符_.数_9) {
                ++I;
                ch = (cast()(Str[I]));
            }
            .追加!(dstring)(pCodes, Str[NumStart .. I - NumStart]);
            uint N = 编译数字.编译!(uint)(pCodes[pCodes.length - 1]); // atoi(pCodes->back().c_str());
            if (N >= ConstraintsSoFar.length || ConstraintsSoFar[N].Type != ConstraintPrefix.isOutput || that.Type != ConstraintPrefix.isInput) {
                return true;
            }
            if (that.isMultipleAlternative) {
                if (multipleAlternativeIndex >= ConstraintsSoFar[N].multipleAlternatives.length) {
                    return true;
                }
                SubConstraintInfo scInfo = ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
                if (scInfo.MatchingInput != -1) {
                    return true;
                }
                scInfo.MatchingInput = ConstraintsSoFar.length;
            }
            else {
                if (.hasMatchingInput(ConstraintsSoFar[N]) && ConstraintsSoFar[N].MatchingInput != ConstraintsSoFar.length) {
                    return true;
                }
                ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.length;
            }
        }
        else if (ch == 字符_.或号) {
            ++multipleAlternativeIndex;
            pCodes = that.multipleAlternatives[multipleAlternativeIndex].Codes;
            ++I;
            ch = (cast()(Str[I]));
        }
        else if (ch == 字符_.异或号) {
            .追加!(dstring)(pCodes, Str[I + 1 .. 2]);
            I += 3;
            ch = (cast()(Str[I]));
        }
        else if (ch == 字符_.艾特) {
            // Multi-letter constraint
            ++I;
            ch = (cast()(Str[I]));
            uint N = (cast(uint)(ch - 字符_.数_0)); // .(Str[I]);
            ++I;
            .追加!(dstring)(pCodes, Str[I .. N]);
            I += N;
            ch = (cast()(Str[I]));
        }
        else {
            .追加!(dstring)(pCodes, Str[I .. 1]);
            ++I;
            ch = (cast()(Str[I]));
        }
    }
    return false;
}
ConstraintInfo[] ParseConstraints(dstring str) {
    ConstraintInfo[] Result = [];
    dstring[] strs = 按字符分割(str, 字符_.逗号); //.split(",");
    {
        for (int I = 0; I < strs.length; ++I) {
            ConstraintInfo ···tempS·0·_2;
            {
                ···tempS·0·_2.Type = ConstraintPrefix.isInput;
                ···tempS·0·_2.isEarlyClobber = false;
                ···tempS·0·_2.MatchingInput = 1;
                ···tempS·0·_2.isCommutative = false;
                ···tempS·0·_2.isIndirect = false;
                ···tempS·0·_2.isMultipleAlternative = false;
                ···tempS·0·_2.Codes = [];
                ···tempS·0·_2.multipleAlternatives = [];
                ···tempS·0·_2.currentAlternativeIndex = 0;
            }
            ConstraintInfo Info = ···tempS·0·_2;
            dstring ConstraintEnd = strs[I];
            // 禁止空 块. 例如 连续的 , 逗号和尾部逗号 x,,z,
            if ((ConstraintEnd is ··null!(dstring)) || .AsmParse(Info, ConstraintEnd, Result)) {
                Result = [];
                break;
            }
            .追加!(ConstraintInfo)(Result, Info);
        }
    }
    return Result;
}
bool Verify(函数类型_ Ty, dstring ConstStr) {
    if (Ty.IsVarArg) {
        return false;
    }
    ConstraintInfo[] Constraints = .ParseConstraints(ConstStr);
    if (Constraints.length == 0) {
        return false;
    }
    int NumOutputs = 0;
    int NumInputs = 0;
    int NumClobbers = 0;
    int NumIndirect = 0;
    {
        for (int i = 0; i < Constraints.length; ++i) {
            switch (Constraints[i].Type) {
                case ConstraintPrefix.isOutput: {
                    if ((NumInputs - NumIndirect) != 0 || NumClobbers != 0) {
                        return // outputs before inputs and clobbers.
                         false;
                    } // outputs before inputs and clobbers.
                    if (!Constraints[i].isIndirect) {
                        ++NumOutputs;
                        break;
                    }
                    ++NumIndirect;
                }
                // 贯穿
                case ConstraintPrefix.isInput: {
                    if (NumClobbers != 0) {
                        return // inputs before clobbers.
                         false;
                    } // inputs before clobbers.
                    ++NumInputs;
                    break;
                }
                case ConstraintPrefix.isClobber: {
                    ++NumClobbers;
                    break;
                }
                default: break;
            }
        }
    }
    switch (NumOutputs) {
        case 0: {
            if (Ty.返回类型.种类 == TypeID_.IntegerTyID) {
                return false;
            }
            break;
        }
        case 1: {
            if (Ty.返回类型.种类 == TypeID_.StructTyID) {
                return false;
            }
            break;
        }
        default: {
            if (Ty.返回类型.种类 != TypeID_.StructTyID || (cast(结构类型_)((Ty.返回类型))).ContainedTys.length != NumOutputs) {
                return false;
            }
            break;
        }
    }
    if (Ty.参数组.length != NumInputs) {
        return false;
    }
    return true;
}
